home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 5
/
Apprentice-Release5.iso
/
Source Code
/
Libraries
/
WASTE 1.2
/
WASTE Demo ƒ
/
WEDemoFiles.c
< prev
next >
Wrap
Text File
|
1996-05-19
|
11KB
|
435 lines
/*
WASTE Demo Project:
File Handling
Copyright © 1993-1996 Marco Piovanelli
All Rights Reserved
C port by John C. Daub
*/
#ifndef __WEDEMOAPP__
#include "WEDemoIntf.h"
#endif
#ifndef __FOLDERS__
#include <Folders.h>
#endif
#define kFileNotOpened -1
OSErr ReadTextFile( const FSSpec *pFileSpec, WEReference we )
{
short dataForkRefNum = kFileNotOpened;
short resForkRefNum = kFileNotOpened;
Handle hText = nil;
Handle hStyles = nil;
Handle hSoup = nil;
Size textSize;
OSErr err;
// open the data fork with read-only permission
if ((err = FSpOpenDF(pFileSpec, fsRdPerm, &dataForkRefNum)) != noErr)
goto cleanup;
// get data fork size
if ((err = GetEOF(dataForkRefNum, &textSize)) != noErr)
goto cleanup;
// set the position in the file from where to start reading
if ((err = SetFPos(dataForkRefNum, fsFromStart, 0L)) != noErr)
goto cleanup;
// try to allocate a handle that large, use temporary memory if available
if ((err = NewHandleTemp(textSize, &hText)) != noErr)
goto cleanup;
// read in the text
HLock(hText);
err = FSRead(dataForkRefNum, &textSize, *hText);
HUnlock(hText);
if (err != noErr)
goto cleanup;
// see if the file has a resource fork
// FSpOpenResFile will return -1 if it fails
if ( ( resForkRefNum = FSpOpenResFile( pFileSpec, fsRdPerm ) ) != kFileNotOpened )
{
// look for a style scrap resource (get the first one; the resource ID doesn't matter)
if ((hStyles = Get1IndResource(kTypeStyles, 1)) != nil)
{
DetachResource(hStyles);
}
// look for a soup resource as well
if ((hSoup = Get1IndResource(kTypeSoup, 1)) != nil)
{
DetachResource(hSoup);
}
}
// insert the text into the WE record
HLock(hText);
if ((err = WEInsert(*hText, textSize, (StScrpHandle) hStyles, hSoup, we)) != noErr)
goto cleanup;
// set the insertion point at the beginning of the text
WESetSelection(0, 0, we);
// reset the WE instance modification count
WEResetModCount( we );
cleanup:
// display an alert box if anything went wrong
if (err != noErr)
{
ErrorAlert( err );
}
ForgetHandle(&hText);
ForgetHandle(&hStyles);
ForgetHandle(&hSoup);
if ( dataForkRefNum != kFileNotOpened )
{
FSClose(dataForkRefNum);
dataForkRefNum = kFileNotOpened;
}
if ( resForkRefNum != kFileNotOpened )
{
CloseResFile(resForkRefNum);
resForkRefNum = kFileNotOpened;
}
return err;
}
// I added a bunch of other functionality to WriteTextFile(), mostly to show how to use
// temp files, check for locked files, etc. ( all along Apple's recommended way of
// doing things. - JCD
OSErr WriteTextFile( const FSSpec * pFileSpec, WEReference we )
{
FInfo fileInfo;
Size textSize;
Boolean replacing;
short dataForkRefNum = kFileNotOpened;
short resForkRefNum = kFileNotOpened;
Handle hText = nil;
StScrpHandle hStyles = nil;
WESoupHandle hSoup = nil;
unsigned long theTime;
Str255 tempFileName;
FSSpec tempFileSpec;
short tempVRef; // volume reference # for the temp file
long tempDirID; // directory ID of the temp file
OSErr err;
// will we be replacing an existing file?
err = FSpGetFInfo( pFileSpec, &fileInfo ) ;
if ( err == noErr )
{
replacing = true;
}
else if ( err == fnfErr )
{
replacing = false;
}
else
{
goto cleanup;
}
// originally, Marco had it so that if the file already existed (replacing == true)
// then just can the original file and move along. for the scope of this demo, that
// really is ok, but generally speaking, not the Apple-recommended way of doing things.
// since we know we're under (at least) System 7 (due to WASTE's need of it), we know
// we can use temporary files, so let us do so!
// also, Marco didn't check for locked files (technically, if a file is locked from
// the Finder, you shouldn't be able to modify it). let's check for that.
// if the file currently exists (meaning it was saved at some time in the past, be it
// 5 minutes ago, or 5 days ago), there is a chance that it could be locked (from the
// Finder's "Get Info" window (or otherwise). If the file is locked, you cannot
// save changes. Therefore, if 'replacing' is true, we have to throw up a message
// saying that we can't do this, then exit.
if ( replacing )
{
if ((err = FSpCheckObjectLock( pFileSpec )) != noErr)
goto cleanup;
// create the temporary file name. the name doesn't have to make sense, just
// be unique
GetDateTime( &theTime );
NumToString( theTime, tempFileName );
// find the temporary items folder on the file's volume; create it if necessary
// it is important that the temp folder (and the temp file) and the "original" target
// file be on the same volume; if not, FSpExchangeFiles will return diffVolErr (-1303)
// and won't work
if ((err = FindFolder( pFileSpec->vRefNum, kTemporaryFolderType, kCreateFolder, &tempVRef, &tempDirID )) != noErr)
goto cleanup;
// make an FSSpec for the temp file
err = FSMakeFSSpec( tempVRef, tempDirID, tempFileName, &tempFileSpec );
if ( (err != noErr) && (err != fnfErr ) )
goto cleanup;
}
// create a new file. if we're replacing, make a temp file. if it's a
// new file from the onset, just create the file
// should we allow people to choose the file to create? i.e. create a TEXT
// file or a ttro file? if you'd like to do this, you'll want to find this
// info out when calling CustomPutFile() and pass that info to this function
if ( replacing )
{
FSpCreateResFile( &tempFileSpec, sigWASTEDemo, kTypeText, smSystemScript );
}
else
{
FSpCreateResFile( pFileSpec, sigWASTEDemo, kTypeText, smSystemScript );
}
if ((err = ResError()) != noErr)
goto cleanup;
// if replacing an old file, copy the old file information
if ( replacing )
{
if ( ( err = FSpSetFInfo( &tempFileSpec, &fileInfo ) ) != noErr )
{
goto cleanup;
}
}
// open the data fork for writing
if ( replacing )
{
err = FSpOpenDF( &tempFileSpec, fsRdWrPerm, &dataForkRefNum );
}
else
{
err = FSpOpenDF( pFileSpec, fsRdWrPerm, &dataForkRefNum );
}
if ( err != noErr )
{
goto cleanup;
}
// set the end-of-file
if ( ( err = SetEOF( dataForkRefNum, 0 ) ) != noErr )
{
goto cleanup;
}
// set the position in the file to write from
if ( ( err = SetFPos( dataForkRefNum, fsFromStart, 0 ) ) != noErr )
{
goto cleanup;
}
// get the text handle from the WE instance
// WEGetText returns the original handle, not a copy, so don't dispose of it!!
hText = WEGetText( we );
textSize = GetHandleSize( hText );
// write the text
HLock( hText );
err = FSWrite( dataForkRefNum, &textSize, *hText );
HUnlock( hText );
if ( err != noErr )
{
goto cleanup;
}
// open the resource file for writing
if ( replacing )
{
resForkRefNum = FSpOpenResFile( &tempFileSpec, fsRdWrPerm );
}
else
{
resForkRefNum = FSpOpenResFile( pFileSpec, fsRdWrPerm );
}
if ( ( err = ResError ( ) ) != noErr )
{
goto cleanup;
}
// allocate temporary handles to hold the style scrap and the soup
// try tapping temporary memory since WECopyRange() could get huge
if ( ( err = NewHandleTemp( 0, (Handle *) &hStyles ) ) != noErr )
{
goto cleanup;
}
if ( ( err = NewHandleTemp( 0, (Handle *) &hSoup ) ) != noErr )
{
goto cleanup;
}
// create the style scrap and the soup
if ( ( err = WECopyRange( 0, LONG_MAX, nil, hStyles, hSoup, we ) ) != noErr )
{
goto cleanup;
}
// make them resource handles
AddResource( (Handle) hStyles, kTypeStyles, 128, "\p" );
if ( ( err = ResError ( ) ) != noErr )
{
goto cleanup;
}
AddResource( (Handle) hSoup, kTypeSoup, 128, "\p" );
if ( ( err = ResError ( ) ) != noErr )
{
goto cleanup;
}
// write them to the resource file
ChangedResource( (Handle)hStyles );
WriteResource( (Handle)hStyles );
if ( ( err = ResError ( ) ) != noErr )
{
goto cleanup;
}
ChangedResource( (Handle)hSoup );
WriteResource( (Handle)hSoup );
if ( ( err = ResError ( ) ) != noErr )
{
goto cleanup;
}
// "clean" this document by resetting the WE instance modification count
WEResetModCount( we );
err = noErr;
cleanup:
// display an alert box if anything went wrong
if (err != noErr)
{
ErrorAlert( err );
}
// remember, don't dispose the hText handle!
ForgetResource( (Handle *) &hStyles );
ForgetResource( (Handle *) &hSoup );
if ( dataForkRefNum != kFileNotOpened )
{
FSClose( dataForkRefNum ) ;
dataForkRefNum = kFileNotOpened ;
}
if ( resForkRefNum != kFileNotOpened )
{
CloseResFile( resForkRefNum ) ;
resForkRefNum = kFileNotOpened ;
}
if ( replacing )
{
// update the disk with any unwritten data
FlushVol( nil, tempFileSpec.vRefNum );
// since we were replacing an existing file, let's now swap the original
// and the temp file. let's hear it for safe saves.
if ( ( err = FSpExchangeFiles( &tempFileSpec, pFileSpec ) ) != noErr )
{
// handle the error
return err;
}
// can the temp file since we don't need it anymore
err = FSpDelete( &tempFileSpec );
if ( err != noErr )
{
// handle the error
return err;
}
}
// and update the disk with any unwritten data
FlushVol( nil, pFileSpec->vRefNum );
return err;
}
/* The following 2 functions (CheckObjectLock and FSpCheckObjectLock) were taken
from MoreFiles 1.2.1, a code sample from Apple's DTS. Here's some info from
the MoreFiles readme:
A collection of File Manager and related routines
by Jim Luther, Apple Macintosh Developer Technical Support
with significant code contributions by Nitin Ganatra, Apple Macintosh Developer
Technical Support
MoreFile Reference is by Eric Soldan
Copyright © 1992-1994 Apple Computer, Inc.
All rights reserved.
Frankly, this is one amazing repository of all sorts of file-related things. I'd
check it out if you can. (should be, as of this writing, on ftp.info.apple.com
in like the /Apple.Support.Services/Developer_Support/ or something like that).
thanx to Alex Rosen for answering my post on comp.sys.mac.programmer.help and pointing
out MoreFiles to me.
WHAT DO THEY DO? Oh duh...i should tell you huh?
Both functions do the same thing: check to see if the object is locked
(in this case, the object is a file). This is using in WriteTextFile()
to prevent overwriting/deleting locked files.
The only difference between these 2 functions are the arguments passed.
the first takes a vRefNum, dirID and a file name, the second takes an FSSpec
and then just calls the first based on the FSSpec (just makes for slighly
neater/readable code)
*/
pascal OSErr CheckObjectLock(short vRefNum, long dirID, StringPtr name)
{
CInfoPBRec pb;
OSErr error;
pb.hFileInfo.ioNamePtr = name;
pb.hFileInfo.ioVRefNum = vRefNum;
pb.hFileInfo.ioDirID = dirID;
pb.hFileInfo.ioFDirIndex = 0; // use ioNamePtr and ioDirID
error = PBGetCatInfoSync(&pb);
if ( error == noErr )
{
// check locked bit
if ( (pb.hFileInfo.ioFlAttrib & 0x01) != 0 )
error = fLckdErr;
}
return ( error );
}
/*****************************************************************************/
pascal OSErr FSpCheckObjectLock(const FSSpec *spec)
{
return ( CheckObjectLock(spec->vRefNum, spec->parID, (StringPtr) spec->name) );
}